package com.oo.chartlibrary.charts;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.oo.chartlibrary.R;

import java.util.ArrayList;

/**
 * Created by zhuxiaolong on 2017/12/17.
 * 功能 1、显示各个项目名称
 * 2、绘制 背景基本图形 圆形 内部多边形 以及内部半径
 * 3、或者 半径上的 圆点
 */

public class RadarChartView extends View implements View.OnTouchListener {
    private final String TAG = getClass().getSimpleName();

    public RadarChartView(Context context) {
        this(context, null, 0);
    }

    public RadarChartView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RadarChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //初始化 xml 获取的属性
        propertyInit(context, attrs, defStyleAttr);
        //获取 初始属性 对画笔进行初始化
        paintInit();
        setOnTouchListener(this);
    }

    /**
     * 动态尺寸转换
     */
    private int toPx(int fromDP) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (density * fromDP + 0.5f);
    }


    /*基本属性*/
    //文字 颜色
    private int itemTextColor;
    //文字 尺寸
    private int itemTextSize;
    //文字偏移量
    private int itemTextOffSet;
    //线条颜色
    private int baseLineColor;
    //线条宽度
    private int baseLineWidth;
    //多边形颜色
    private int shapeColor;
    //标值点 颜色
    private int anchorColor;
    //标值点尺寸
    private int anchorSize;

    private void propertyInit(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        TypedArray typedArray = context.getTheme()
                .obtainStyledAttributes(attrs, R.styleable.RadarChartView, defStyleAttr, 0);
        //文字颜色 默认白色
        itemTextColor = typedArray.getColor(R.styleable.RadarChartView_itemTextColor, Color.WHITE);
        //文字尺寸
        itemTextSize = typedArray.getDimensionPixelOffset(R.styleable.RadarChartView_itemTextSize, toPx(15));
        //文字 偏移量
        itemTextOffSet = typedArray.getDimensionPixelOffset(R.styleable.RadarChartView_itemTextOffSet, toPx(4));
        //线条颜色
        baseLineColor = typedArray.getColor(R.styleable.RadarChartView_baseLineColor, Color.WHITE);
        //线条宽度
        baseLineWidth = typedArray.getDimensionPixelOffset(R.styleable.RadarChartView_baseLineWidth, toPx(1));
        //多边形颜色
        shapeColor = typedArray.getColor(R.styleable.RadarChartView_shapeColor, Color.GRAY);
        //锚点颜色
        anchorColor = typedArray.getColor(R.styleable.RadarChartView_anchorColor, Color.WHITE);
        //锚点尺寸
        anchorSize = typedArray.getDimensionPixelSize(R.styleable.RadarChartView_anchorSize, toPx(3));
        typedArray.recycle();
    }

    /*基本数据集合*/
    private String[] itemText;


    /*进行基本尺寸的计算*/
    //drawRect
    private RectF drawRect;
    //绘制背景图的 rect
    private RectF baseLineRect;
    //由item 数量 确定各个内部线条的角度
    private int avrAngle = 60;
    //开始角度
    private int startAngle = 0;
    //itemText 锚点 数组
    private PointF[] textPointList;
    //itemAnchorPoint
    private PointF[] anchorPointList;
    //中心点
    float centerX = 0;
    float centerY = 0;


    /**
     * measure 尺寸获取  暂时不用  只需要用 onSizeChanged
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 获取尺寸
     * 这里要获取 可以绘制的尺寸  出去四周的 padding
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        int leftPadding = getPaddingLeft();
        int topPadding = getPaddingTop();
        int rightPadding = getPaddingRight();
        int bottomPadding = getPaddingBottom();
        //可绘制部分 还要去除文字宽度 正方形区域
        int textPadding = (int) (itemTextSize * 5 + itemTextOffSet + 0.5f);
        int size = 0;
        if (w > h) {//如果绘制区域 宽度大 以高度为准进行计算
            size = h - topPadding - bottomPadding - textPadding;
        } else {//如果绘制区域 高度大 以宽度为绘制标准进行计算
            size = w - leftPadding - rightPadding - textPadding;
        }
        //中心点
        centerX = w * 0.5f;
        centerY = h * 0.5f;
        //四边
        float l = centerX - size * 0.5f;
        float t = centerY - size * 0.5f;
        float r = centerX + size * 0.5f;
        float b = centerY + size * 0.5f;
        drawRect = new RectF(l, t, r, b);
        baseLineRect = new RectF(l, t, r, b);
    }


    /*图像生成部分 绘制*/
    //基础画笔
    private Paint basePaint;
    //文字画笔
    private Paint textPaint;
    //shape画笔
    private Paint shapePaint;
    //point 画笔
    private Paint pointPaint;

    private void paintInit() {
        //基础部分
        basePaint = new Paint();
        basePaint.setAntiAlias(true);
        basePaint.setColor(baseLineColor);
        basePaint.setStyle(Paint.Style.STROKE);
        basePaint.setStrokeWidth(baseLineWidth);
        //锚点
        pointPaint = new Paint();
        pointPaint.setColor(baseLineColor);
        pointPaint.setStrokeWidth(anchorSize);
        pointPaint.setStrokeCap(Paint.Cap.ROUND);
        //文字部分
        textPaint = new Paint();
        textPaint.setColor(itemTextColor);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTextSize(itemTextSize);
        textPaint.setAntiAlias(true);
        //图形部分
        shapePaint = new Paint();
        shapePaint.setColor(shapeColor);
        shapePaint.setStyle(Paint.Style.FILL);
    }

    /**
     * 绘制部分
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制 基础背景圆形
        drawCircle(canvas);
        //绘制 线条
        if (itemNames != null && itemNames.length > 0) {
            drawLines(canvas, itemNames);
            drawShape(canvas, anchorPointList);
        }
    }

    /**
     * 绘制 内部多边形
     */
    private void drawShape(Canvas canvas, PointF[] anchorPoints) {
        if (anchorPoints != null && anchorPoints.length > 0) {
            PointF p;
            Path path = new Path();
            for (int i = 0; i < anchorPoints.length; i++) {
                //计算 线段的起始点
                p = anchorPoints[i];
                if (i == 0) {
                    path.moveTo(p.x, p.y);
                } else {
                    path.lineTo(p.x, p.y);
                }
            }
            path.close();
            canvas.drawPath(path, shapePaint);
        }
    }


    /**
     * 根据 item 名字数量 计算角度
     * 绘制 各个线条 采用 path 方法绘制
     */
    private void drawLines(Canvas canvas, ItemData[] itemData) {
        int num = itemData.length;
        //角度计算 采用角度计算 计算坐标时再转为 弧度
        float avrAngle = 360 / num;
        //半径
        float radius = baseLineRect.width() * 0.5f;// width = heigh
        //每条线的弧度
        float lineAngle;
        float stopX = 0;
        float stopY = 0;
        //point
        PointF pointF;
        //textBound
        Rect bound = new Rect();
        //循环计算第 i 条线的端点
        for (int i = 0; i < num; i++) {
            lineAngle = startAngle + i * avrAngle;

            float sinY = (float) Math.sin(Math.toRadians(-lineAngle));
            float cosX = (float) Math.cos(Math.toRadians(-lineAngle));

            stopY = centerY - (radius * sinY);
            stopX = centerX + (radius * cosX);
            //绘制直线
            canvas.drawLine(centerX, centerY, stopX, stopY, basePaint);
            //绘制文字
            float textX = stopX;
            float textY = stopY;
            float tw = textPaint.measureText(itemData[i].name);
            textY = centerY - ((radius + tw) * sinY);
            textX = centerX + ((radius + tw) * cosX);
            canvas.drawText(itemData[i].name, textX, textY, textPaint);
            //计算 标记点
            float pointLX = centerX + itemData[i].value * radius / 10 * cosX;
            float pointLY = centerY - itemData[i].value * radius / 10 * sinY;
            pointF = new PointF(pointLX, pointLY);
            anchorPointList[i] = pointF;
            //画点
            canvas.drawPoint(pointF.x, pointF.y, pointPaint);
        }
    }

    /**
     * 绘制 基础圆
     */
    private void drawCircle(Canvas canvas) {
        float radius = Math.min(baseLineRect.width(), baseLineRect.height()) * 0.5f;
        canvas.drawCircle(centerX, centerY, radius, basePaint);
    }


    public void setItemTextSize() {

    }

    /*数据设置*/
    public void setStartAngle(int angle) {
        startAngle = angle % 360;
        invalidate();
    }

    private ItemData[] itemNames;

    public void setItemData(ArrayList<ItemData> itemnames) {
        ItemData[] names = new ItemData[itemnames.size()];
        itemnames.toArray(names);
        anchorPointList = new PointF[itemnames.size()];
        setItemData(names);
    }

    public void setItemData(ItemData[] itemnames) {
        this.itemNames = itemnames;
        invalidate();
    }


    /*触摸监听 触摸到图形时 根据移动量 更改开始角度*/
    //默认设置 图表拦截触摸事件
    private boolean chartTouchable = true;
    //记录 初始 touch 位置 当触点移动时  根据与圆心成的角度进行 旋转
    private PointF beginPoint;
    private int touchBeginAngle = 0;
    private int touchSwipeAngle = 0;


    public boolean isChartTouchable() {
        return chartTouchable;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (!chartTouchable) {
            return false;
        }
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            //记录
            beginPoint = new PointF(event.getX(), event.getY());
            //根据 tan 计算 弧度
            double piA = Math.atan((-beginPoint.y + centerY) / (beginPoint.x - centerX));
            // 转为角度
            touchBeginAngle = (int) Math.toDegrees(piA);
            Log.i(TAG, "onTouch:  初始  弧度：  " + piA + "   角度 ：" + touchBeginAngle);
        }
        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            //移动位置 计算 所成角度 通知重绘
            double curPiB = Math.atan((-centerY + event.getY()) / (event.getX() - centerX));
            int curAngle = (int) Math.toDegrees(curPiB);
            Log.i(TAG, "onTouch:  滑动  弧度：  " + curPiB + "   角度 ：" + curAngle);
            setStartAngle(curAngle - touchBeginAngle);
        }
        if (event.getAction() == MotionEvent.ACTION_UP) {
            beginPoint = null;
        }
        return true;
    }


    public static class ItemData {
        public ItemData(String name, int value) {
            this.name = name;
            this.value = value;
        }

        private String name;
        private int value;

    }
}
